/*
 * @Descripttion: 工具集
 * @version: 1.2
 * @LastEditors: sakuya
 * @LastEditTime: 2022年5月24日00:28:56
 */

import CryptoJS from 'crypto-js'
import sysConfig from "@/config"

const tool = {}

/* localStorage */
tool.data = {
	set (key, data, datetime = 0) {
		//加密
		if (sysConfig.LS_ENCRYPTION == "AES") {
			data = tool.crypto.AES.encrypt(JSON.stringify(data), sysConfig.LS_ENCRYPTION_key)
		}
		let cacheValue = {
			content: data,
			datetime: parseInt(datetime) === 0 ? 0 : new Date().getTime() + parseInt(datetime) * 1000
		}
		return localStorage.setItem(key, JSON.stringify(cacheValue))
	},
	get (key) {
		try {
			const value = JSON.parse(localStorage.getItem(key))
			if (value) {
				let nowTime = new Date().getTime()
				if (nowTime > value.datetime && value.datetime != 0) {
					localStorage.removeItem(key)
					return null
				}
				//解密
				if (sysConfig.LS_ENCRYPTION == "AES") {
					value.content = JSON.parse(tool.crypto.AES.decrypt(value.content, sysConfig.LS_ENCRYPTION_key))
				}
				return value.content
			}
			return null
		} catch (err) {
			return null
		}
	},
	remove (key) {
		return localStorage.removeItem(key)
	},
	clear () {
		return localStorage.clear()
	}
}

/*sessionStorage*/
tool.session = {
	set (table, settings) {
		var _set = JSON.stringify(settings)
		return sessionStorage.setItem(table, _set)
	},
	get (table) {
		var data = sessionStorage.getItem(table)
		try {
			data = JSON.parse(data)
		} catch (err) {
			return null
		}
		return data
	},
	remove (table) {
		return sessionStorage.removeItem(table)
	},
	clear () {
		return sessionStorage.clear()
	}
}

/*cookie*/
tool.cookie = {
	set (name, value, config = {}) {
		var cfg = {
			expires: null,
			path: null,
			domain: null,
			secure: false,
			httpOnly: false,
			...config
		}
		var cookieStr = `${name}=${escape(value)}`
		if (cfg.expires) {
			var exp = new Date()
			exp.setTime(exp.getTime() + parseInt(cfg.expires) * 1000)
			cookieStr += `;expires=${exp.toGMTString()}`
		}
		if (cfg.path) {
			cookieStr += `;path=${cfg.path}`
		}
		if (cfg.domain) {
			cookieStr += `;domain=${cfg.domain}`
		}
		document.cookie = cookieStr
	},
	get (name) {
		var arr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"))
		if (arr != null) {
			return unescape(arr[2])
		} else {
			return null
		}
	},
	remove (name) {
		var exp = new Date()
		exp.setTime(exp.getTime() - 1)
		document.cookie = `${name}=;expires=${exp.toGMTString()}`
	}
}

/* Fullscreen */
tool.screen = function (element) {
	var isFull = !!(document.webkitIsFullScreen || document.mozFullScreen || document.msFullscreenElement || document.fullscreenElement)
	if (isFull) {
		if (document.exitFullscreen) {
			document.exitFullscreen()
		} else if (document.msExitFullscreen) {
			document.msExitFullscreen()
		} else if (document.mozCancelFullScreen) {
			document.mozCancelFullScreen()
		} else if (document.webkitExitFullscreen) {
			document.webkitExitFullscreen()
		}
	} else {
		if (element.requestFullscreen) {
			element.requestFullscreen()
		} else if (element.msRequestFullscreen) {
			element.msRequestFullscreen()
		} else if (element.mozRequestFullScreen) {
			element.mozRequestFullScreen()
		} else if (element.webkitRequestFullscreen) {
			element.webkitRequestFullscreen()
		}
	}
}

/* 复制对象 */
tool.objCopy = function (obj) {
	return JSON.parse(JSON.stringify(obj))
}

/* 日期格式化 */
tool.dateFormat = function (date, fmt = 'yyyy-MM-dd hh:mm:ss') {
	date = new Date(date)
	var o = {
		"M+": date.getMonth() + 1,                 //月份
		"d+": date.getDate(),                    //日
		"h+": date.getHours(),                   //小时
		"m+": date.getMinutes(),                 //分
		"s+": date.getSeconds(),                 //秒
		"q+": Math.floor((date.getMonth() + 3) / 3), //季度
		"S": date.getMilliseconds()             //毫秒
	}
	if (/(y+)/.test(fmt)) {
		fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length))
	}
	for (var k in o) {
		if (new RegExp("(" + k + ")").test(fmt)) {
			fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)))
		}
	}
	return fmt
}

/**
 * 获取某个日期的农历
 * @parmas {newDate} 日期 年-月-日
 */
tool.getLunar = function (newDate) {

	var nyear
	var nmonth
	var nday = -1
	var nwday
	var nhrs
	var nmin
	var nsec
	var newDate = newDate

	var lmonth, lday, lleap //农历参数

	function Draw () {
		NewTick()

		//显示时间
		var s = nyear + '年' + nmonth + '月' + nday + '日 ' + '星期' + cweekday(nwday) + ' ' + shapetime(nhrs, nmin, nsec)
		s += " 农历" + lmonth + "月" + lday //农历
		var lunar_month_day = lmonth + "月" + lday
		return lunar_month_day
	}


	function NewTick () {
		var noww = newDate ? new Date(newDate) : new Date()
		if (noww.getDate() != nday) {
			nyear = noww.getFullYear()
			nmonth = noww.getMonth() + 1
			nwday = noww.getDay()
			nday = noww.getDate()

			getlunar() //获取农历
		}
		nhrs = noww.getHours()
		nmin = noww.getMinutes()
		nsec = noww.getSeconds()
	}


	//辅助函数
	var hzWeek = new Array("日", "一", "二", "三", "四", "五", "六", "日")
	function cweekday (wday) {
		return hzWeek[wday]
	}
	function shapetime (vhrs, vmin, vsec) {
		if (vsec <= 9) vsec = "0" + vsec
		if (vmin <= 9) vmin = "0" + vmin
		if (vhrs <= 9) vhrs = "0" + vhrs
		return vhrs + ":" + vmin + ":" + vsec
	}

	//农历函数开始
	var lunarInfo = new Array(0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, //1990
		0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, 0x14b63)
	function lYearDays (y) {
		var i, sum = 348
		for (i = 0x8000; i > 0x8; i >>= 1) sum += (lunarInfo[y - 1900] & i) ? 1 : 0
		return (sum + leapDays(y))
	}
	function leapDays (y) {
		if (leapMonth(y)) return ((lunarInfo[y - 1900] & 0x10000) ? 30 : 29)
		else return (0)
	}
	function leapMonth (y) {
		return (lunarInfo[y - 1900] & 0xf)
	}
	function monthDays (y, m) {
		return ((lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29)
	}
	function Lunar (y, m, d) {
		var i, leap = 0,
			temp = 0
		var offset = (Date.UTC(y, m, d) - Date.UTC(1900, 0, 31)) / 86400000
		for (i = 1900; i < 2050 && offset > 0; i++) {
			temp = lYearDays(i)
			offset -= temp
		}
		if (offset < 0) {
			offset += temp
			i--
		}
		this.year = i
		leap = leapMonth(i)
		this.isLeap = false
		for (i = 1; i < 13 && offset > 0; i++) {
			if (leap > 0 && i == (leap + 1) && this.isLeap == false) {
				--i
				this.isLeap = true
				temp = leapDays(this.year)
			} else {
				temp = monthDays(this.year, i)
			}
			if (this.isLeap == true && i == (leap + 1)) this.isLeap = false
			offset -= temp
		}
		if (offset == 0 && leap > 0 && i == leap + 1) if (this.isLeap) {
			this.isLeap = false
		} else {
			this.isLeap = true; --i
		}
		if (offset < 0) {
			offset += temp; --i
		}
		this.month = i
		this.day = offset + 1
	}
	var nStr1 = new Array('', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二')
	var nStr2 = new Array('初', '十', '廿', '卅', '□')
	function GetcDay (d) {
		var s
		switch (d) {
			case 10:
				s = '初十'
				break
			case 20:
				s = '二十'
				break
			case 30:
				s = '三十'
				break
			default:
				s = nStr2[Math.floor(d / 10)]
				s += nStr1[d % 10]
				break
		}
		return (s)
	}
	function GetcMon (m) {
		if (m == 1) return '正'
		else return nStr1[m]
	}
	function getlunar () {
		var lObj = new Lunar(nyear, nmonth - 1, nday)
		lmonth = GetcMon(lObj.month)
		lday = GetcDay(lObj.day)
		lleap = lObj.isLeap
		if (lleap == 1) {
			lmonth = "闰" + lmonth
		}
	}
	//农历函数结束
	return Draw()
}


/* 千分符 */
tool.groupSeparator = function (num) {
	num = num + ''
	if (!num.includes('.')) {
		num += '.'
	}
	return num.replace(/(\d)(?=(\d{3})+\.)/g, function ($0, $1) {
		return $1 + ','
	}).replace(/\.$/, '')
}

/* 常用加解密 */
tool.crypto = {
	//MD5加密
	MD5 (data) {
		return CryptoJS.MD5(data).toString()
	},
	//BASE64加解密
	BASE64: {
		encrypt (data) {
			return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(data))
		},
		decrypt (cipher) {
			return CryptoJS.enc.Base64.parse(cipher).toString(CryptoJS.enc.Utf8)
		}
	},
	//AES加解密
	AES: {
		encrypt (data, secretKey, config = {}) {
			if (secretKey.length % 8 != 0) {
				console.warn("[SCUI error]: 秘钥长度需为8的倍数，否则解密将会失败。")
			}
			const result = CryptoJS.AES.encrypt(data, CryptoJS.enc.Utf8.parse(secretKey), {
				iv: CryptoJS.enc.Utf8.parse(config.iv || ""),
				mode: CryptoJS.mode[config.mode || "ECB"],
				padding: CryptoJS.pad[config.padding || "Pkcs7"]
			})
			return result.toString()
		},
		decrypt (cipher, secretKey, config = {}) {
			const result = CryptoJS.AES.decrypt(cipher, CryptoJS.enc.Utf8.parse(secretKey), {
				iv: CryptoJS.enc.Utf8.parse(config.iv || ""),
				mode: CryptoJS.mode[config.mode || "ECB"],
				padding: CryptoJS.pad[config.padding || "Pkcs7"]
			})
			return CryptoJS.enc.Utf8.stringify(result)
		}
	}
}

export default tool
